package com.authorization.common.utils;

import com.authorization.client.client.util.ln.CHZipUtils;
import com.authorization.client.client.util.secret.*;
import com.authorization.common.utils.exception.BusinessException;
import com.authorization.common.utils.security.Md5Utils;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.springframework.core.io.ClassPathResource;

import java.io.*;
import java.util.Base64;
import java.util.Map;
import java.util.Objects;

@Slf4j
public class CreateLic {
    private static String prik = "128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263";
    private static String pubk = "040AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857";


    public static String createLicFile(JSONObject json) {


        //五个文件 SM2密钥对
        String userpath = json.get("userid") == null ? "so-2018-4" : json.get("userid").toString();
        String path = System.getProperty("user.dir") + "/lic/" + userpath;
        String soPath = System.getProperty("user.dir") + "/licso";
        String soFile = "libJavaJNI.so";
        String licPath = System.getProperty("user.dir") + "/licbin/" + userpath;
        String licfile = "so.lic";
        Global.keyPath = path;
        isExist(path);
        isExist(licPath);
        createSM2s(path);
        createSM2g(path);
        // SO文件
/*        try {
            System.out.println("复制 so文件 " + soPath + "/" + soFile + " 到" + path + "/" + soFile);
            copyFile(soPath + "/" + soFile, path + "/" + soFile);
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }*/
        //info文件及key文件
        createInfo(path, json);
        //生成
        createlics(path, licPath + "/" + licfile);
        //  FileWrite( licPath +"/base64.lic",  CHZipUtils.fileToBase64(licPath + "/" + licfile));
        //  CHZipUtils.base64toFile(CHZipUtils.fileToBase64(licPath + "/" + licfile),licPath+"/lic2.lic");
        System.out.println("生成文件位置:" + licPath + "/" + licfile);
        return licPath + "/" + licfile;
    }

    public static void isExist(String path) {
        File file = new File(path);
//判断文件夹是否存在,如果不存在则创建文件夹
        if (!file.exists()) {
            file.mkdirs();
        }
    }
    /**
     * V5改造之后的授权管理
     * @param json 返回文件路径
     * @return
     */
    public static String createLicFileV5(JSONObject json) {
        /** 1 文件路径**/
        String path = getPath(json.get("userid") == null ? "so-2018-4" : json.get("userid").toString());
        String licPath = getLicPath(json.get("userid") == null ? "so-2018-4" : json.get("userid").toString());
        String v5Path = getV5LicPath(json.get("userid") == null ? "so-2018-4" : json.get("userid").toString());
        String licfile = "v5so.lic";
        String v5file = "v5so.zip";
        Global.keyPath = path;
        isExist(v5Path);
        isExist(path);
        isExist(licPath);
        String macName =  ((String) json.get("machineCode")).split(":")[0];
        String macAddr =  ((String) json.get("machineCode")).split(":")[1];

        /** 2 SM2随机生成密钥对**/
        Map<String , Object> sm2Map = Sm2Util.createKey();

        //解密mac地址
        try {
            macAddr = new String(Base64.getDecoder().decode(macAddr)).trim().toUpperCase();
        }catch (RuntimeException e){
            new BusinessException("001", "机器码错误");
        }

        /** 2.1  加密公钥 （公钥+机器指纹 用AES算法加密） 生成publicKey文件**/
        createLicFile(path, "publicKey", CryptAES.encrypt((String)sm2Map.get("publicKey"), macAddr));

        /** 2.1  加密私钥 （授权信息） 生成info文件**/
        String infoPath = createNewInfo(path, json, (String)sm2Map.get("privateKey"));

        /** 3 授权文件MD5加密 生成MD5文件**/
        try {
            createLicFile(path, "md5" ,  Md5Utils.fileMD5(infoPath));
        } catch (IOException e) {
            log.info(e.getMessage());
        }

        /** 4 生成网卡名称文件**/
        createLicFile(path, "mac", macName);

        /** 5 生成Sigar文件**/
        createSigarFile(licPath);

        /** 6 生成lic文件**/
        createlics(path, licPath + "/" + licfile);

        /** 7 生成v5ZIP文件**/
        createlics(licPath, v5Path + "/" + v5file);

        log.info("生成文件位置:" + licPath + "/" + licfile);
        return v5Path +"/" + v5file;
    }

    /**
     * 生成Sigar文件
     * @param licPath
     */
    private static void createSigarFile(String licPath) {
        ClassPathResource desktopResource = new ClassPathResource("static/sigar/desktop.ini");
        ClassPathResource libsigarAdmin64 = new ClassPathResource("static/sigar/libsigar-amd64-linux.so");
        ClassPathResource libsigarAdmin86 = new ClassPathResource("static/sigar/libsigar-x86-linux.so");
        ClassPathResource libsigarWin64 = new ClassPathResource("static/sigar/sigar-amd64-winnt.dll");
        String sigarPath = licPath + "/" +"sigar";
        FileUtil.createFile(sigarPath);
        try {
            FileUtil.writeToLocal(sigarPath + "/" + "desktop.ini" ,desktopResource.getInputStream());
            FileUtil.writeToLocal(sigarPath + "/" + "libsigar-amd64-linux.so" ,libsigarAdmin64.getInputStream());
            FileUtil.writeToLocal(sigarPath + "/" + "libsigar-x86-linux.so" ,libsigarAdmin86.getInputStream());
            FileUtil.writeToLocal(sigarPath + "/" + "sigar-amd64-winnt.dll" ,libsigarWin64.getInputStream());
        } catch (IOException e) {
            log.error("读取静态文件失败"+ e.getMessage());
        }
    }

    /**
     * 创建Lic文件
     * @param path
     * @param fileName
     * @param key
     */
    private static void createLicFile(String path, String fileName, String key) {
        FileWrite(path + "/" + fileName, key);
    }


    /**
     * V5版创建授权文件
     * @param path
     * @param json
     * @param privateKey
     */
    private static String createNewInfo(String path, JSONObject json, String privateKey) {
        System.out.println("原值：" + json.toString());
        String en = SM2Utils.encrypt(privateKey, json.toString());
        System.out.println("SM2加密后");
        String sb2 = "";
        StringBuilder sbs = new StringBuilder();
        sbs.append(en.toString());
        sb2 = sbs.reverse().toString();
        System.out.println(sb2);
        FileWrite(path + "/info", sb2);
        createKey(path, json.getString("userid"));
        return path + "/info";
    }

    /**
     * 根据用户编号生成V5文件路径
     * @param userid
     * @return
     */
    private static String getV5LicPath(String userid) {
        return  System.getProperty("user.dir") + "/v5lic/" + userid;
    }

    /**
     * 根据用户编号生成Lic文件路径
     * @param userid
     * @return
     */
    private static String getLicPath(String userid) {
        return  System.getProperty("user.dir") + "/licbin/" + userid;
    }

    /**
     * 根据用户编号生成路径
     * @param userid
     * @return
     */
    private static String getPath(String userid) {
        return  System.getProperty("user.dir") + "/lic/" + userid;
    }

    private static void copyFile(String sourcePath, String destFile)
            throws IOException {

        File source = new File(sourcePath);
        File dest = new File(destFile);

        InputStream input = null;
        OutputStream output = null;

        try {
            input = new FileInputStream(source);
            output = new FileOutputStream(dest);

            byte[] buf = new byte[1024];
            int bytesRead;
            while ((bytesRead = input.read(buf)) > 0) {
                output.write(buf, 0, bytesRead);
            }
        } finally {
            input.close();
            output.close();
        }
    }

    /**
     * 创建授权文件
     *
     * @param path 存放位置
     * @param json
     */
    public static void createInfo(String path, JSONObject json) {

        String userid = json.getString("userid");
        System.out.println("原值：" + json.toString());
        String en = SM2Utils.encrypt(pubk, json.toString());
        System.out.println("SM2加密");
        String sb2 = "";
//        try {
//            JavaJNI jni = new JavaJNI();
//            JavaJNI javaJNI = new JavaJNI();
//            sb2 = javaJNI.getKey(en.toString());
//        } catch (Exception err) {
            StringBuilder sbs = new StringBuilder();
            sbs.append(en.toString());
            sb2 = sbs.reverse().toString();
//        }


        System.out.println(sb2);
        FileWrite(path + "/info", sb2);
        createKey(path, userid);

    }

    public static void createInfo(String path) {
        //第一位客户编号,1、	客户编号 userid
//            2、	加密开关 isSecret
//            3、	主程序版本： mainVersion
//            4、	加密服务版本:  secretVersion
//            5、	客户全称 username
//            6、	购买微服务 services 加一个说明ALL代表不限
//            7、	授权开始日期 begiDate
//            8、	停止日期 endDate
//            9、	客户数量 contacts 加一个说明MAX代表不限
//            10、	行为数量 behavior 加一个说明MAX代表不限
        String userid = "devuser", isSecret = "1";

        String mainVersion = "v1.0", secretVersion = "v2_", username = "测试客户", services = "ALL";
        String begiDate = "2018-06-29", endDate = "2020-06-29";
        String contacts = "1000", behavior = "1000";
        JSONObject json = new JSONObject();
        json.put("userid", userid);
        json.put("isSecret", isSecret);

        json.put("mainVersion", mainVersion);
        json.put("secretVersion", secretVersion);
        json.put("username", username);
        json.put("services", services);
        json.put("begiDate", begiDate);
        json.put("endDate", endDate);
        json.put("contacts", contacts);
        json.put("behavior", behavior);

        System.out.println("原值：" + json.toString());
        String en = SM2Utils.encrypt(pubk, json.toString());
        System.out.println("加密后：" + en);
        JavaJNI javaJNI = new JavaJNI();
        String sb2 = javaJNI.getKey(en.toString());
        System.out.println("C++加密后：" + sb2);
        String sb3 = javaJNI.getKey(sb2.toString());
        System.out.println("C++解密后：" + sb3);
        String de = SM2Utils.decrypt(prik, sb3);
        System.out.println("解密后：" + de);
        FileWrite(path + "/info", sb2);
        createKey(path, userid);


    }

    public static void createKey(String path, String userid) {


        String key = SM2Utils.encrypt(pubk, userid.toString());
        FileWrite(path + "/key", key);

    }

    public static void createSM2s(String path) {

        FileWrite(path + "/sm2s", prik);


    }

    public static void createSM2g(String path) {

        FileWrite(path + "/sm2g", pubk);


    }


    public static void FileWrite(String filepath, String value) {
        FileOutputStream out = null;
        FileOutputStream outSTr = null;
        BufferedOutputStream Buff = null;
        FileWriter fw = null;
        try {
            outSTr = new FileOutputStream(new File(filepath));

            Buff = new BufferedOutputStream(outSTr);
            long begin0 = System.currentTimeMillis();

            Buff.write(value.getBytes());

            Buff.flush();
            Buff.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 创建密文文件(压缩)
     *
     * @param path
     */
    public static void createlics(String path, String zipPath) {
        System.out.println("添加密文");

        //压缩

        CHZipUtils.zip(path, zipPath);


    }

    public static void main(String[] args) {
        String src = "D://java/service/authorization/authorization/licbin/321233";
        String src1 = "D:\\java\\service\\authorization\\authorization/licbin/321233";

        Objects.equals("" , "");


        //isExist(src);
        File file = new File(src);
        file.mkdirs();

    }


}
